#include <iostream>
#include <sys/select.h>
#include <string>
#include <map>
#include "Sock.hpp"

// fd_set是位图结构，所以可以表示的文件描述符大小是sizeof(fd_set) * 8
#define NUM (sizeof(fd_set) * 8)

// 记录要让select等待的fd
int fd_array[NUM];

void Usage(char* args)
{
    std::cout << "Usage: " << args << " PORT" << std::endl; 
}

// ./server 8080
int main(int argc, char* argv[])
{
    if(argc != 2)
    {
        Usage(argv[0]);
        exit(1);
    }

    for(int i = 0; i < NUM; ++i)
    {
        // -1代表此位置的描述符不能使用，fd>=0代表为正常的描述符
        fd_array[i] = -1;
    }
    
    uint16_t port = atoi(argv[1]);
    int listen_sock = Sock::Socket();
    Sock::Bind(listen_sock, port);
    Sock::Listen(listen_sock);

    fd_array[0] = listen_sock;

    fd_set rfs;

    // 创建一个字典
    std::map<std::string, std::string> dict;
    dict["hello"] = "你好";
    dict["apple"] = "苹果";
    dict["banana"] = "香蕉";
    dict["orange"] = "橙子";
    dict["grape"] = "葡萄";

    while(1)
    {
        FD_ZERO(&rfs);

        int Max = listen_sock;
        for(int i = 0; i < NUM; ++i)
        {
            if(fd_array[i] >= 0)
            {
                FD_SET(fd_array[i], &rfs);
                if(fd_array[i] > Max)
                {
                    Max = fd_array[i];
                }
            }
        }
        int ret = select(Max + 1, &rfs, nullptr, nullptr, nullptr);
        
        switch (ret)
        {
        case -1:
            std::cerr << "select error" << std::endl;
            sleep(1);
            break;
        case 0:
            std::cout << "select timeout" << std::endl;
            break;
        default:
            std::cout << "waiting succeed!" << std::endl;

            for(int i = 0; i < NUM; ++i)
            {
                if(fd_array[i] == -1)
                    continue;

                if(FD_ISSET(fd_array[i], &rfs))
                {
                    if(fd_array[i] == listen_sock)
                    {
                        int new_sock = Sock::Accept(listen_sock);
                        std::cout << "listen_sock获取到新连接: " << new_sock << std::endl;

                        for(int i = 1; i < NUM; ++i)
                        {
                            if(fd_array[i] == -1)
                            {
                                fd_array[i] = new_sock;
                                std::cout << "已将新连接放入等待数组fd_array[" << i << "]" << std::endl;
                                break;
                            }
                            
                            if(i == NUM - 1)
                            {
                                std::cout << "连接已满" << std::endl;
                                close(new_sock);
                                break;
                            }
                        }
                    }
                    else
                    {
                        std::cout << "sock: " << fd_array[i] << " 上面有普通读取" << std::endl;
                        char buf[1024] = {0};
                        ssize_t s = recv(fd_array[i], buf, sizeof(buf) - 1, 0);

                        if(s > 0)
                        {
                            // 网络读取apple实际检测出来是 “apple \n” 一共七个字符，很奇怪
                            std::cout << "读取到了" << s << "个字符" << std::endl;
                            
                            // int i = 0;
                            // for(auto it = rec.begin(); it != rec.end(); ++it, ++i)
                            // {
                            //     std::cout << i << " : " << *it << std::endl;
                            // }

                            buf[s - 1] = 0;
                            buf[s - 2] = 0;
                            std::cout << "[" <<fd_array[i] << "]# " << buf << std::endl;
                            std::string tmp("server# ");

                            // std::string rec(buf);
                            // int j = 0;
                            // for(auto it = rec.begin(); it != rec.end(); ++it, ++j)
                            // {
                            //     std::cout << j << " : " << *it << std::endl;
                            // }

                            // std::cout << dict.count(buf) << std::endl;
                            // std::cout << dict.count("apple") << std::endl;
                            
                            if(dict.count(buf))
                            {   
                                tmp += dict[buf];
                            }
                            else
                            {
                                tmp += buf;
                            }
                            tmp += '\n';
                            send(fd_array[i], tmp.c_str(), tmp.size(), 0);
                        }
                        else if(s == 0)
                        {
                            std::cout << "对端已关闭连接" << std::endl;
                            close(fd_array[i]);
                            fd_array[i] = -1;
                            std::cout << "已将本连接关闭，并在数组fd_array[" << i << "]中抹去" <<std::endl;
                        }
                        else
                        {
                            // 读取错误
                            close(fd_array[i]);
                            fd_array[i] = -1;
                            std::cout << "已将本连接关闭，并在数组fd_array[" << i << "]中抹去" <<std::endl;
                        }
                        
                    }
                }
            }
            break;
        }
    }
    return 0;
}